# -*- coding: utf-8 -*-
"""
Created on Fri Dec 14 15:16:49 2012

@author: Winand
"""
from __future__ import with_statement
if __name__ == '__main__': import sys, os; sys.path.append(os.path.dirname(__file__))

import cgi, httplib, os
from server import try_conn, init_server
from webapi.general import ddict, localPath
from settings import REQUESTHANDLERS, STATIC_PREFIX
#import time
import threading
sync = threading.Lock()

def expandStatusCode(code):
    return str(code)+' '+httplib.responses[code]
    
def HandleRequest(mod, f, *arglist):
    for i, handler in enumerate(REQUESTHANDLERS):
        cls = getattr(mod, handler)()
        midf = getattr(cls, f, False) or getattr(cls, 'Handle_ALL', False)
        if i == len(REQUESTHANDLERS)-1: #last resort handler
            midf(*arglist)
        elif midf:
            if midf(*arglist): return

#Serve static files in debug environment
def ServeStatic(resp):
    contenttype = {
        '.css': "text/css",
        '.js': "application/x-javascript"
        }
    filepath = localPath(resp.path)
    try:
        #prevent directory traversal, though browser does this before us
        if not filepath.startswith(localPath(STATIC_PREFIX)): raise IOError()
        with open(filepath, 'rb') as f:
            resp.headers['Content-Type'] = \
                            contenttype.get(os.path.splitext(resp.path)[1], \
                            "application/octet-stream")
            resp.text = f.read()
    except IOError:
        print "Failed to load static file", resp.path
        
#def filtDict(d, f):
#    return dict((k, v) for k, v in d.iteritems() if k in f)

def application(environ, start_response):
#    print "thread", threading.currentThread().ident, os.getpid()
#    req_start_time = time.clock()    
        
    resp=ddict()
    resp.code = 200
    resp.headers = {'Content-Type': "text/html"}
    resp.text = ""
    resp.file = ""
    resp.env = environ
    resp.path = environ['PATH_INFO']
    resp.cookie = environ.get('HTTP_COOKIE', "")
    resp.client = environ['REMOTE_ADDR'] #client address
    resp.secure = environ.get('wsgi.url_scheme', None) == "https"

    if environ['REQUEST_METHOD'] == "POST":
#TODO: do we need to check CONTENT_TYPE for 'application/x-www-form-urlencoded', 'multipart/form-data' ?
        qs,environ['QUERY_STRING'] = environ['QUERY_STRING'], ''
        resp.post_query = cgi.FieldStorage(fp=environ['wsgi.input'], \
                                    environ=environ, keep_blank_values=True)
        environ['QUERY_STRING'] = qs
    elif environ['REQUEST_METHOD'] == "GET":
        resp.query = cgi.FieldStorage(environ=environ, keep_blank_values=True)
    
    if resp.path.startswith(STATIC_PREFIX) or \
    resp.path in ("/robots.txt", "/favicon.ico"): #static file requested
        print "Reconfigure webserver to handle static files", resp.path
        ServeStatic(resp)
    elif try_conn(): #make sure main server app is running
        with sync: #make server single-threaded, this will not concern forking server
            import middleware
            HandleRequest(middleware, 'Handle_'+environ['REQUEST_METHOD'], resp)
    else:
        init_server() #Start server
        resp.code = 200
        resp.headers['Content-Type'] = "text/html"
        from settings import TEMPLATEFIELDS
        resp.text = """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="%d" />
<link rel="stylesheet" href="/static/styles/base.css">
<title>lancomm</title>
</head>
<body>
<div class="pagestyle mainblock" style="background: #e6f1fa url(/static/images/anim.gif) repeat; margin-top:auto; margin-bottom:auto;">
<h1>Server is starting...</h1>
<p align="center">%s, %s</p></div>
</body>
</html>""" % (3, TEMPLATEFIELDS["creator"], TEMPLATEFIELDS["year_cr"])

    resp.code = expandStatusCode(resp.code)
    ct = cgi.parse_header(resp.headers['Content-Type'])
    if ct[0].split("/")[0] == "text" and not 'charset' in ct[1]:
        resp.headers['Content-Type'] += "; charset=utf-8"
    #if Content-Disposition isn't specified for non-text content and we can find out filename
    elif len(resp.file) and not 'Content-Disposition' in resp.headers:
        resp.headers['Content-Disposition']='attachment; filename="'+ os.path.basename(resp.file) +'"'
    headers=[] #expand headers with list values
    for i in resp.headers.items():
        headers+=[(i[0], j) for j in i[1]] if type(i[1]) is list else (i,)
    start_response(resp.code, headers)
#    print 'Request time', time.clock() - req_start_time
    if len(resp.file):
        fobj = file(resp.file, 'rb')
        #mod_wsgi will calc Content-Length
        return environ['wsgi.file_wrapper'](fobj)
    else:
        resp.headers['Content-Length'] = str(len(resp.text))
        return [resp.text]

if __name__ == '__main__':
    from SocketServer import ThreadingMixIn
    from wsgiref.simple_server import WSGIServer, make_server
    class ThreadedWSGIServer(ThreadingMixIn, WSGIServer): pass
    httpd = make_server('', 81, application, ThreadedWSGIServer)
    httpd.serve_forever()
